/*-------------------------------------------------------------------------
 *
 * scanner.h
 *		核心扫描器的 API（flex 机器）
 *
 * 核心扫描器也由 PL/pgSQL 使用，因此我们为其提供了公共 API。
 * 然而，后端的其余部分仅期望使用 parser.h 提供的高级 API。
 *
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/parser/scanner.h
 *
 *-------------------------------------------------------------------------
 */

#ifndef SCANNER_H
#define SCANNER_H

#include "common/keywords.h"

/*
 * 扫描器在此联合类型中返回扫描的标记的额外数据。
 * 注意，这些是使用在基于扫描器构建的bison解析器中的YYSTYPE字段的一个子集。
 */
typedef union core_YYSTYPE
{
	int			ival;			/* 用于整数字面量 */
	char	   *str;			/* 用于标识符和非整数字面量 */
	const char *keyword;		/* 关键字的规范拼写 */
} core_YYSTYPE;

/*
 * 我们跟踪的标记位置是从源字符串开始的字节偏移量，
 * 而不是bison默认使用的列号/行号表示。此外，为了减少开销，
 * 我们仅跟踪每个构造的一个位置（通常是第一个标记位置），
 * 而不是bison默认所做的开头和结束位置。因此，只需将YYLTYPE定义为一个int。
 */
#define YYLTYPE  int

/*
 * 扫描器API的另一个重要组成部分是标记代码编号。
 * 然而，这些在此文件中未定义，因为bison坚持自己定义它们。
 * 核心扫描器使用的标记代码是ASCII字符加上这些：
 *	%token <str>	IDENT UIDENT FCONST SCONST USCONST BCONST XCONST Op
 *	%token <ival>	ICONST PARAM
 *	%token			TYPECAST DOT_DOT COLON_EQUALS EQUALS_GREATER
 *	%token			LESS_EQUALS GREATER_EQUALS NOT_EQUALS
 * 上述标记定义*必须*是构建在此扫描器之上的任何bison解析器中声明的第一个
 * 定义，以便为它们分配一致的编号（具体来说，IDENT = 258，依此类推）。
 */

/*
 * flex扫描器允许我们传递的YY_EXTRA数据。
 * 核心扫描器所需的私有状态在此处。注意，实际的
 * yy_extra结构可能更大，并且将此作为其第一个组件，从而
 * 允许调用的解析器在YY_EXTRA中保留一些自己的字段。
 */
typedef struct core_yy_extra_type
{
	/*
	 * 扫描器正在物理扫描的字符串。我们主要保留此信息，以便
	 * 能够廉价地计算当前标记（yytext）的偏移量。
	 */
	char	   *scanbuf;
	Size		scanbuflen;

	/*
	 * 要使用的关键字列表以及相关的语法标记代码。
	 */
	const ScanKeywordList *keywordlist;
	const uint16 *keyword_tokens;

	/*
	 * 要使用的扫描器设置。这些是通过scanner_init()从对应的
	 * GUC变量初始化的。如果调用者在scanner_init()后不希望扫描器
	 * 的行为遵循当前的GUC设置，可以对此进行修改。
	 */
	int			backslash_quote;
	bool		escape_string_warning;
	bool		standard_conforming_strings;

	/*
	 * literalbuf 用于在需要多个规则解析
	 * 单个文字值时累积文字值。调用 startlit() 将缓冲区重置为空，调用 addlit() 添加文本。 注意：literalbuf 中的字符串不一定是以 null 结尾的，但在偏移量 literallen 处始终可以添加一个尾随的 null。只有在需要时，我们才存储一个 null。
	 */
	char	   *literalbuf;		/* palloc'd 可扩展缓冲区 */
	int			literallen;		/* 实际当前字符串长度 */
	int			literalalloc;	/* 当前分配的缓冲区大小 */

	/*
	 * 随机混合的扫描器状态。
	 */
	int			state_before_str_stop;	/* 结束引号之前的起始条件 */
	int			xcdepth;		/* 斜杠星号注释中的嵌套深度 */
	char	   *dolqstart;		/* 当前$foo$引号起始字符串 */
	YYLTYPE		save_yylloc;	/* PUSH_YYLLOC() 的一元素栈 */

	/* Unicode 转义的 UTF16 代理对的第一部分 */
	int32		utf16_first_part;

	/* 文本词法警告的状态变量 */
	bool		warn_on_first_escape;
	bool		saw_non_ascii;
#ifdef FDD
	char		gb18030Flag;//0非gb18030编码，1为gb18030编码，2正在进行gb18030编码拼接
#endif //FDD
} core_yy_extra_type;

/*
 * yyscanner 的类型在 scan.l 外部是不可见的。
 */
typedef void *core_yyscan_t;

/* 支持 scanner_errposition_callback 函数 */
typedef struct ScannerCallbackState
{
	core_yyscan_t yyscanner;
	int			location;
	ErrorContextCallback errcallback;
} ScannerCallbackState;


/* 从 parser/scan.l 导出的常量数据 */
extern PGDLLIMPORT const uint16 ScanKeywordTokens[];

/* parser/scan.l 中的入口点 */
extern core_yyscan_t scanner_init(const char *str,
								  core_yy_extra_type *yyext,
								  const ScanKeywordList *keywordlist,
								  const uint16 *keyword_tokens);
extern void scanner_finish(core_yyscan_t yyscanner);
extern int	core_yylex(core_YYSTYPE *lvalp, YYLTYPE *llocp,
					   core_yyscan_t yyscanner);
extern int	scanner_errposition(int location, core_yyscan_t yyscanner);
extern void setup_scanner_errposition_callback(ScannerCallbackState *scbstate,
											   core_yyscan_t yyscanner,
											   int location);
extern void cancel_scanner_errposition_callback(ScannerCallbackState *scbstate);
extern void scanner_yyerror(const char *message, core_yyscan_t yyscanner) pg_attribute_noreturn();

#endif							/* SCANNER_H */
